# Chatper 6

# Using Interactive Forms

CONTENTS

- Building a JavaScript-Compatible HTML Form
  - Understanding Form Actions and Methods
  - Overview of Form Elements
- Creating an HTML Form
- Using `form` Objects in JavaScript
  - `form` Object Properties
  - `form` Object Methods and Events
- The JavaScript `form` Object Hierarchy
  - Text Fields and Password Fields
  - Text Areas
  - Checkboxes
  - Radio Buttons
  - Selection Lists
  - Hidden Fields
  - Buttons
  - File Upload Fields
- Automating the Form with JavaScript
- Adding Automatic Totals
- Automating the Shipping Address
- Validating the Form Data with Event Handlers
  - Where to Validate?
  - Which Fields to Validate?
- Creating Functions for Validation
- Adding an Event Handler for Validation
- Workshop Wrap-Up
  - Next Steps
  - Q&A

In this chapter you'll explore one of the most powerful uses for JavaScript: working with HTML forms. You can use JavaScript to make a form more interactive, to validate data the user enters, and to enter data based on other data.

Let's begin with a basic order form for an imaginary company and use JavaScript to add features to the form. Along the way you'll learn about the various form elements, how they relate to JavaScript, and just what you can do with each one.

## Building a JavaScript-Compatible HTML Form

HTML started out as a read-only language; you could present information to readers and allow them to follow links to sites with different information, but there was no way to accept input from the user.

The advent of HTML forms changed things considerably. Forms added new HTML tags that could take input from the user. This enables you easily to create a fill-out form to register users or take orders, or for any other purpose.

Before you build a sample form, let's start with a quick overview of the elements you can use in a form. Each of these will relate to a JavaScript object, which is discussed later in this chapter.

### Understanding Form Actions and Methods

By itself, an HTML form can only hold information; it can't send it to the server. This part of the job is accomplished by Common Gateway Interface (CGI), a standard for server-side applications. When you press the SUBMIT button on a form, the data in the fields is sent to the CGI program, which can act on the data-mail you a response, send a result back to the user, or add an item to a database.

When you submit the form data, it is sent to the server using one of two methods:

- The `GET` method places the data in the URL itself.
- The `POST` method sends the data as a block of input.

You'll learn about the technical aspects of these methods and which you should use in Chapter 17, "Combining JavaScript, CGI, and SSI." Basically, it will depend on the data and on what the CGI script you are using supports. For the moment, you can use either one.

Because JavaScript can't communicate with the server, it doesn't eliminate the need for CGI; instead, it enables you to control the data as it is entered and check it for accuracy before the CGI program receives it. This saves you work creating the CGI program. In fact, you can easily use the same CGI program for many different forms. One such script is presented in Chapter 17.

Tip
It is possible to have a JavaScript-only form. You used simple forms in Chapter 5 "Accessing Window Elements as Objects," to interact with the user. You'll find many more examples throughout this book.

After the CGI script receives the data, it sends a response back to the user. This can send the user to a different Web page or can generate a page "on the fly" and display it.

### Overview of Form Elements

An HTML form begins with the `<FORM>` tag. This tag indicates that a form is beginning, and it enables form elements to be used. The `<FORM>` tag includes three parameters:

- `NAME` is simply a name for the form. You can use forms without giving them names, but you'll need to assign a name in order to use the form with JavaScript.
- `METHOD` is either `GET` or `POST`; these are the two ways the data can be sent to the server.
- `ACTION` is the CGI script that the form data will be sent to when submitted. You'll look at an actual script in Chapter 17. You can also use the `mailto:` action to send the form's results to an e-mail address.

For example, here is a `<FORM>` tag for a form named `Order`. This form uses the `GET` method and sends its data to a CGI script called `order.cgi` in the same directory as the Web page itself:

>     <FORM NAME="Order" METHOD="GET" ACTION="order.cgi">

For a form that will be processed entirely by JavaScript (such as a calculator or interactive game), the `METHOD` and `ACTION` attributes are not needed. You can use a simple `<FORM>` tag that names the form:

>     <FORM NAME="calcform">

The `<FORM>` tag is followed by one or more form elements. These are the data fields in the form, such as text fields and checkboxes. You will look at each type of element in the following sections. After all the elements comes the form ending tag, `</FORM>`. After this tag, you can't use form elements without starting another form.

Note
You can also include any normal HTML elements within the `<FORM>` tags. This is useful for labeling each of the elements.

#### Text Fields and Text Areas

Many of the form elements use the `<INPUT>` tag. This tag is followed by a `TYPE` parameter to determine which type of input is expected. The first such field is the `TEXT` field. This is the simplest of the form elements; it enables the user to enter text in a one-line area. The following is an example of a simple `TEXT` field:

>     <INPUT TYPE="TEXT" NAME="text1" VALUE="hello" SIZE="30">

This defines a text field called `text1`. The field is given a default value of `"hello"` and allows up to 30 characters to be entered.

An alternate form of text field is the `PASSWORD` field. This is a specialized text field that displays the text as asterisks on the screen. This type of input is often used for passwords so that observers don't see which password is being entered. The password field is defined like `TEXT`:

>     <INPUT TYPE="PASSWORD" NAME="pass1" SIZE=30>

A third option is the text area, which allows multiple lines of text to be entered. Rather than using the `<INPUT>` tag, text areas are defined with a special tag, `<TEXTAREA>`. Here is a typical `<TEXTAREA>` definition:

>     <TEXTAREA NAME="text1" ROWS="2" COLS="70">
>     This is the content of the TEXTAREA tag.
>     </TEXTAREA>

The text between the opening and closing `<TEXTAREA>` tags is used as the initial value for the text area. This type of tag is ideal when you need a larger amount of information, such as a complete address or a paragraph of text. You can include line breaks within the default value.

Figure 6.1 shows examples of `TEXT`, `PASSWORD`, and `TEXTAREA` tags on an HTML page, as displayed by Netscape.

Figure 6.1 : An example of the `TEXT, PASSWORD,` and `TEXTAREA` form elements.

#### Checkboxes, Radio Buttons, and Selection Lists

For some parts of your form, you may want to ask simple questions: yes/no questions, multiple-choice questions, and so on. Three form elements make it easy to do this.

The first element is the checkbox; this simply displays a box that can be checked or unchecked. The `chECKBOX` type to the `INPUT` tag is used to create a checkbox, as follows:

>     <INPUT TYPE="chECKBOX" NAME="check1" VALUE="Yes" chECKED>

Again, this gives a name to the form element. The `VALUE` attribute assigns a meaning to the checkbox; this is a value that is returned if the box is checked. The default value is "on." Finally, the `chECKED` attribute can be included to make the box checked by default.

Another element for decisions is the radio button, using the `<INPUT>` tag's `RADIO` type. These buttons are similar to checkboxes, but they exist in groups, and only one button can be checked in each group. These are used for a multiple-choice or "one of many" input. Here's an example of a group of radio buttons:

>     <INPUT TYPE="RADIO" NAME="radio1" VALUE="Option1" chECKED> Option 1
>     <INPUT TYPE="RADIO" NAME="radio1" VALUE="Option2"> Option 2
>     <INPUT TYPE="RADIO" NAME="radio1" VALUE="Option3"> Option 3

Once again, the `NAME` attribute is used; in this case, it names the entire group of radio buttons. All the buttons with the same name are considered to be in a group. The `VALUE` attribute gives each button a name; this is essential so that you can tell which one is pressed.

A final form element is also useful for multiple-choice selections: the `<SELECT>` HTML tag is used to define a selection list, or a multiple-choice list of text items. This is an example of a selection list:

>     <SELECT NAME="select1" SIZE=40>
>     <OPTION VALUE="choice1" SELECTED>This is the first choice.
>     <OPTION VALUE="choice2">This is the second choice.
>     <OPTION VALUE="choice3">This is the third choice.
>     </SELECT>

Each of the `OPTION` tags defines one of the possible choices. The `VALUE` attribute is the name that is returned to the program, and the text outside the `OPTION` tag is displayed as the text of the option.

An optional attribute to the `SELECT` tag, `MULTIPLE`, can be specified to allow multiple items to be selected. Browsers usually display a single-selection `SELECT` as a drop-down list and a multiple-selection list as a scrollable list.

Figure 6.2 is an example of an HTML page in Netscape that shows examples of checkboxes, radio buttons, and single- and multiple-selection lists.

Figure 6.2 : An example of the display of checkboxes, radio buttons, and selection lists.

#### Hidden Fields

HTML form elements include a special type of field: the hidden field. This includes a name and a value, similar to a text field; however, you can't edit it, and it is not displayed on the Web page. Hidden fields are useful for passing information to the CGI script or between multiple scripts.

A hidden field uses the `<INPUT>` tag and simply has a name and a value. For example, this command defines a hidden field called `score` with a value of `40200`:

>     <INPUT TYPE="HIDDEN" NAME="score" VALUE="40200">

#### SUBMIT and RESET Buttons

The final type of form element is a button. Buttons use the `<INPUT>` tag and can use one of three different types:

- `type=SUBMIT` is a submit button. This button causes the data in the form fields to be sent to the CGI script.
- `type=RESET` is a reset button. This button sets all the form fields back to their default value, or blank.
- `type=BUTTON` is a generic button. This button performs no action on its own, but you can assign it one using JavaScript.

All three types of buttons include a `NAME` to identify the button, and a `VALUE` that indicates the text to display on the button's face. A few buttons were used in the examples in Chapter 5. As an example, the following defines a `SUBMIT` button with the name `sub1` and the value `"Click Here"`:

>     <INPUT TYPE="SUBMIT" NAME="sub1" VALUE="Click Here">

## Creating an HTML Form

Using the form elements discussed, let's create an order form for a fictional software company called, coincidentally enough, Fictional Software Company (FSC). This company sells four products: a word processor, a spreadsheet, a database, and an instruction booklet. You will use the following elements:

- Text fields for the buyer's name, phone number, and e-mail address, and text areas for the billing and shipping address.
- Because the company has only four products, there's room to list them all on the form. Each has its own text fields for quantity and cost.
- A total cost text field is used to store the total cost. The user then selects the method of payment from the selection list and enters a credit card number or check number if needed.
- Finally, a SUBMIT button enables users to send the order, and a RESET button enables them to start over with the defaults.

Listing 6.1 shows the complete HTML form, and Figure 6.3 shows Netscape's display of the form.

Figure 6.3 : The first draft of the FSC order form.

> Listing 6.1. The HTML document for the order form.

>     <HTML>
>     <HEAD><TITLE>Order Form</TITLE></HEAD>
>     <BODY>
>     <H1>Order Form</H1>
>     <FORM NAME="order">
>     <B>Name:</B> <INPUT TYPE="text" NAME="name1" SIZE=20>
>     <B>Phone: </B><INPUT TYPE="text" NAME="phone" SIZE=15>
>     <B>E-mail address:</B><INPUT TYPE="text" NAME="email" SIZE=20><BR>
>     <B>Billing and Shipping Addresses:</B><BR>
>     <TEXTAREA NAME="billto" COLS=40 ROWS=4>
>     Enter your billing address here.
>     </TEXTAREA>
>     <TEXTAREA NAME="shipto" COLS=40 ROWS=4>
>     Enter your shipping address here.
>     </TEXTAREA>
>     <B>Products to Order:</B><BR>
>     Qty: <INPUT TYPE="TEXT" NAME="qty1" VALUE="0" SIZE=4>
>     Cost: <INPUT TYPE="TEXT" NAME="cost1" SIZE=6>
>     ($40.00 ea) Fictional Spreadsheet 7.0 <BR>
>     Qty: <INPUT TYPE="TEXT" NAME="qty2" VALUE="0" SIZE=4>
>     Cost: <INPUT TYPE="TEXT" NAME="cost2" SIZE=6>
>     ($69.95 ea) Fictional Word Processor 6.0<BR>
>     Qty: <INPUT TYPE="TEXT" NAME="qty3" VALUE="0" SIZE=4>
>     Cost: <INPUT TYPE="TEXT" NAME="cost3" SIZE=6>
>     ($99.95 ea) Fictional Database 7.0 <BR>
>     Qty: <INPUT TYPE="TEXT" NAME="qty4" VALUE="0" SIZE=4>
>     Cost: <INPUT TYPE="TEXT" NAME="cost4" SIZE=6>
>     ($4.95 ea) Instruction Booklet for the above <HR>
>     <B>Total Cost:</B>
>     <INPUT TYPE="TEXT" NAME="totalcost" SIZE=8><HR>
>     <B>Method of Payment</B>:
>     <SELECT NAME="payby">
>     <OPTION VALUE="check" SELECTED>Check or Money Order
>     <OPTION VALUE="cash">Cash or Cashier's Check
>     <OPTION VALUE="credit">Credit Card (specify number)
>     </SELECT><BR>
>     <B>Credit Card or Check Number:</B>:
>     <INPUT TYPE="TEXT" NAME="creditno" SIZE="20"><BR>
>     <INPUT TYPE="SUBMIT" NAME="submit" VALUE="Send Your Order">
>     <INPUT TYPE="RESET" VALUE="Start Over">
>     </FORM>
>     </BODY>
>     </HTML>

Forms like this one are used all over the Web. As you can see, this form isn't very user-friendly; the user has to calculate the cost for each item and the total cost. You will use JavaScript to add automatic calculation and other interactive features later in this chapter.

## Using `form` Objects in JavaScript

Before you continue working with the order form, let's look at the way JavaScript handles form data. Each form in your HTML page is represented in JavaScript by a `form` object. The `form` object has the same name as the `NAME` attribute in the `<FORM>` tag you used to define it.

Alternately, you can use the `forms` array to refer to forms. This array includes an item for each form element, indexed starting with zero. For example, if the first form in a document has the name `form1`, you can refer to it in one of two ways:

>     document.form1
>     document.forms[0]

### `form` Object Properties

The most important property of the `form` object is the `elements` array, which contains an object for each of the form elements. You can refer to an element by its own name or by its index in the array. For example, these expressions both refer to the first element in the `order` form, the `name1` text field:

>     document.order.elements[0]
>     document.order.name1

Note
Both forms and elements can be referred to with their own names, or as indices in the `forms` and `elements` arrays. For clarity, this chapter will use individual form and element names rather than array references.

If you do refer to forms and elements as arrays, you can use the `length` property to determine the number of objects in the array: `document.forms.length` is the number of forms in a document, and `document.form1.elements.length` is the number of elements in the `form1` form.

Along with the elements, each `form` object also has a list of properties, most of which are defined by the corresponding `<FORM>` tag. You can also set these from within JavaScript. They include the following:

- `action` is the form's `ACTION` attribute, or the program to which the form data will be submitted.
- `encoding` is the `MIME` type of the form, specified with the `EncTYPE` attribute. In most cases, this is not needed.
- `length` is the number of elements in the form.
- `method` is the method used to submit the form, either `GET` or `POST`.
- `target` specifies the window in which the result of the form (from the CGI script) will be displayed. Normally, this is done in the main window, replacing the form itself.

### `form` Object Methods and Events

The `form` object has two event handlers, `onSubmit` and `onReset`. You can specify a group of JavaScript statements or a function call for these events within the `<FORM>` tag that defines the form.

If you specify a statement or function for the `onSubmit` event, the statement is called before the data is submitted to the CGI script. You can prevent the submission from happening by returning a value of `false` from the `onSubmit` event handler. If the statement returns `true`, the data will be submitted. In the same fashion, you can prevent a RESET button from working with an `onReset` event handler.

The `form` object has two methods, `submit()` and `reset()`. You can use these methods to submit the data or reset the form yourself, without requiring the user to press a button. The `submit()` method should be used only in special cases; it's generally bad manners to send data to the server without the user's permission.

Note
You can use a `mailto` URL in the `ACTION` attribute of a form and have the data mailed to you instead of submitted to a CGI script. Using the `submit()` method with such an action enabled scripts to obtain information about your computer or to send mail from your address without your knowledge. Because of this potential security and privacy concern, Netscape disabled the submit method for mailto URLs.

## The JavaScript `form` Object Hierarchy

The elements of a form each have their own object classes, and each of these has certain properties, methods, and events. In the next sections, you will look at each type of JavaScript object used for form elements in detail.

One property applies to all form elements: the `type` property is a string that describes the type of element. For most of the elements, this is the value you specified in the `TYPE` attribute of the `<INPUT>` tag. The exceptions are the following:

- For text areas (defined with `<TEXTAREA>`), the type is `"textarea"`.
- For single selection lists (defined with `<SELECT>`), the type is `"select-one"`.
- For selection lists that include the `MULTIPLE` attribute, the type is `"select-multiple"`.

Another property that applies to all `form` elements is the `form property`, which indicates an element's parent `form object`.

### Text Fields and Password Fields

Text fields are the simplest field to work with in JavaScript. Password fields are nearly identical; the main difference is that the text is not displayed. The `text` and `password` objects have the following properties:

- `name` is the name given to the field. This is also used as the object name.
- `defaultValue` is the default value; this corresponds to the `VALUE` attribute. This is a read-only property.
- `value` is the current value. This starts out the same as the default value, but can be changed-either by the user or by JavaScript functions.

Most of the time when you work with text fields, you will use the `value` attribute to read the value the user has entered, or to change the value. For example, this statement changes the value of a text field called username in the `order` form to `"John Q. User"`:

>     document.order.username.value = "John Q. User"

Note
For security reasons, you cannot normally access the `value` property of a `password` object in JavaScript. You can access it if you enable data tainting, as explained in Chapter 10, "Working with Multiple Pages and Data."

#### Text Field Methods

The `text` and `password` objects also have a few methods you can use:

- `focus()` sets the focus to the field. This positions the cursor in the field and makes it the "current" field.
- `blur()` is the opposite; it removes the focus from the field.
- `select()` selects the text in the field, just as a user can do with the mouse. You cannot currently select only part of a field.

Tip
These aren't the only methods you can use with text fields; don't forget that because the `value` property is a `String` object, you can use any of the `String` methods on the value. The `String` object is explained in Chapter 4 "Using Built-In Objects and Custom Objects."

#### Text Field Events

The `text` and `password` objects support the following event handlers:

- The `onFocus` event happens when the text field gains focus.
- The `onBlur` event happens when the text field loses focus.
- The `onChange` event happens when the user changes the text in the field, then moves out of it.
- The `onSelect` event happens when the user selects some or all of the text in the field. Unfortunately, there's no way to tell exactly which part of the text was selected.

If used, these event handlers should be included in the `<INPUT>` tag declaration. For example, the following is a text field including an `onChange` event that displays an alert:

>     <INPUT TYPE="TEXT" NAME="text1" onChange="window.alert('Changed.');">

### Text Areas

Text areas are defined with their own tag, `<TEXTAREA>`, and are represented by the `textarea` object. This object includes the same properties, methods, and event handlers as the `text` and `password` objects. For example, this `<TEXTAREA>` tag includes an `onFocus` event handler to change the status line:

>     <TEXTAREA NAME="text2" onFocus = "window.status = 'got focus.';">Default Value</TEXTAREA>

There is one difference about a text area's value: it can include more than one line, with end-of-line characters between. This can be complicated by the fact that the end-of-line character is different on the three platforms (`\r\n` in Windows; `\n` in UNIX and Macintosh). Be sure to check for both types when needed.

If you are placing your own values into a text field, the latest version of JavaScript automatically converts any end-of-line characters to match the user's platform, so you can use either type.

Note
This is an example of a platform-specific issue within JavaScript; although JavaScript is intended as a platform-independent language, there are still a few stubborn features. See Chapter 14, "Debugging JavaScript Programs," for additional information.

### Checkboxes

A checkbox is simple: it has only two states. Nevertheless, the checkbox object has four different properties:

- `name` is the name of the checkbox, and also the object name.
- `value` is the "true" value for the checkbox-usually `on`. This value is used by the server to indicate that the checkbox was checked. In JavaScript, you should use the `checked` property instead.
- `defaultChecked` is the default status of the checkbox, assigned by the `chECKED` attribute.
- `checked` is the current value (true for checked, and false for unchecked).

To manipulate the checkbox or use its value, you use the `checked` attribute. For example, this statement turns on a checkbox called `same` in the `order` form:

>     document.order.same.checked = true;

The checkbox has a single method, `click()`. This method simulates a click on the box. It also has a single event, `onClick`, which occurs whenever the checkbox is clicked. This happens whether the box was turned on or off, so you'll need to check the `checked` property.

Caution
The `click()` method does not work properly in some versions of Netscape. You should avoid it when possible.

### Radio Buttons

Radio buttons are similar to checkboxes, but an entire group of them shares a single name and a single object. You can refer to the following properties of the `radio` object:

- `name` is the name common to the radio buttons.
- `length` is the number of radio buttons in the group.

To access individual buttons, you treat the radio object as an array. The buttons are indexed, starting with `0`. Each individual button has the following properties:

- `value` is the value assigned to the button. (This is used by the server.)
- `defaultChecked` indicates the value of the `chECKED` attribute and the default state of the button.
- `checked` is the current state.

For example, you can check the first radio button in the `radio1` group on the `form1` form with this statement:

>     document.form1.radio1[0].checked = true;

However, if you do this, be sure you set the other values to `false` as needed. This is not done automatically. You can use the `click` method to do both of these in one step.

Like a checkbox, radio buttons have a `click()` method and an `onClick` event handler. Each radio button can have a separate statement for this event.

Note
A bug in Netscape Navigator 2.0 causes radio buttons to be indexed backward; index `0` will actually be the last button on the page. This is fixed in version 3.0 and later, but watch out for strange behavior when users use an old version.

### Selection Lists

A selection list is similar to radio buttons, because the entire group of options shares a name. In this case, the data for each element is stored in the `options` array, which indexes the different options starting with `0`.

The object for selection lists is the `select` object. The object itself has the following properties:

- `name` is the name of the selection list.
- `length` is the number of options in the list.
- `options` is the array of options (explained later).
- `selectedIndex` returns the index value of the currently selected item. You can use this to check the value easily. In a multiple-selection list, this indicates the first selected item.

The `options` array has a single property of its own, `length`, which indicates the number of selections. In addition, each item in the `options` array has the following properties:

- `index` is the index into the array.
- `defaultSelected` indicates the state of the `SELECTED` attribute.
- `selected` is the current state of the option. Setting this property to `true` selects the option. You can select multiple options if the `MULTIPLE` attribute is included in the `<SELECT>` tag.
- `name` is the value of the `NAME` attribute. This is used by the server.
- `text` is the text that is displayed in the option. In Netscape 3.0 or later, you can change this value.

The `select` object has two methods, `blur()` and `focus()`. These perform the same purpose as the corresponding methods for `text` objects. The event handlers are `onBlur`, `onFocus`, and `onChange`, also similar to other objects.

You can change selection lists dynamically-for example, choosing a product in one list could control which options are available in another list. You can also add and delete options from the list. You will look at these capabilities in Chapter 11, "Real-Life Examples II."

Note
The `onChange` event doesn't work for select lists in some versions of Netscape . It does work properly in version 3.0 and later.

### Hidden Fields

Hidden fields are stored in `hidden` objects. This object has two properties, `name` and `value`. These function similarly to a text field. There are no methods or event handlers for the hidden object-it can't be changed, so the user can't really mess with a hidden field.

### Buttons

Buttons can be defined as SUBMIT buttons, RESET buttons, or generic BUTTON buttons. All of these types have the same properties, methods, and events.

Buttons support the `name` property, used to identify the button, and the `value` property, which defines the button's text. You cannot change either of these values. Buttons support a single method, `click()`, and an event handler, `onClick`.

The `onClick` action is performed with any button. In the case of a generic button, nothing else happens. In a SUBMIT or RESET button, you can prevent the submission or resetting by returning a false value.

Note
As with radio buttons and checkboxes, the `click` method may not work with some older versions of Netscape. Check your version before attempting to use it, and expect trouble from users of older versions.

### File Upload Fields

A relatively new feature of Netscape enables you to define a file upload field on a form. This enables the user to upload a file to the server. You can define a file upload field with an `<INPUT>` tag:

>     <INPUT TYPE="file" NAME="fname">

Because this field is mainly for interacting with the server, JavaScript has little control over it. A `FileUpload` object represents the field, and you can access two properties:

- `name` is the name of the field, as defined in the `<INPUT>` tag.
- `value` is the name of the file (if any) the user is uploading.

## Automating the Form with JavaScript

You now have quite a bit of information about the many form-related objects and how they can be used in JavaScript. Let's bring this information into the real world by demonstrating how you can add friendly, interactive features to the FSC order form created earlier in this chapter.

## Adding Automatic Totals

At present, the order form isn't any more convenient than a paper one-the user still has to calculate the total for each item and the grand total manually. Let's use JavaScript to make those functions automatic. You will do this with the `onChange` event handler, so each time a quantity is changed, the associated totals will be updated.

To start with, you will make each item's cost field update when its quantity field is changed. To do this, you'll use the `onChange` event handler for each of the quantity text fields. For example, here's what the first one will look like:

>     Qty: <INPUT TYPE="TEXT" NAME="qty1" VALUE="0" SIZE=4
>     onChange = "UpdateCost(1, 40.00);">

This calls a function called `UpdateCost()`, which takes two parameters: the item number to update (`1` through `4`) and the associated unit cost. You then need to define the `UpdateCost()` function in the HTML header. Here's the function:

>     // function to update cost when quantity is changed
>     function UpdateCost(number, unitcost) {
>        costname = "cost" + number;
>        qtyname = "qty" + number;
>        var q = document.order[qtyname].value;
>        document.order[costname].value = q * unitcost;
>        Total();
>     }

This function stores the item number and unit cost in the `number` and `unitcost` variables. It then constructs names for the cost and quantity elements; because they have been named consistently (such as `qty1` through `qty4`), this is simple.

A temporary variable, `q`, is used to hold the quantity field's current value. Notice that you have to use brackets around `qtyname`, because you want to use the value of this variable, not its actual name. The quantity in `q` is then multiplied by the unit cost and stored in the appropriate cost text field.

Finally, you include a function call for the `Total()` function, which will calculate the total cost each time a field is changed. Here is the definition for this function:

>     // function to calculate the total cost field
>     function Total() {
>        var tot = 0;
>        tot += (40.00 * document.order.qty1.value);
>        tot += (69.95 * document.order.qty2.value);
>        tot += (99.95 * document.order.qty3.value);
>        tot += (4.95 * document.order.qty4.value);
>        document.order.totalcost.value = tot;

`}`

This function simply uses a temporary variable called `tot` to add up each of the costs, which it gets by multiplying the appropriate prices by the quantities. It then stores the value of `tot` in the total cost text field.

Listing 6.2 shows the revised HTML order form including the new functions. You now have an order form that updates automatically-each time you enter or change a quantity, the cost for that item and the total cost are updated. Figure 6.4 shows the order form after several quantities have been entered.

Figure 6.4 : The order form with automatically updated numeric totals.

> Listing 6.2. The revised HTML order form, including automatic update functions.

>     <HTML>
>     <HEAD><TITLE>Order Form</TITLE>
>     <SCRIPT>
>     // function to calculate the total cost field
>     function Total() {
>        var tot = 0;
>        tot += (40.00 * document.order.qty1.value);
>        tot += (69.95 * document.order.qty2.value);
>        tot += (99.95 * document.order.qty3.value);
>        tot += (4.95 * document.order.qty4.value);
>        document.order.totalcost.value = tot;
>     }

>     // function to update cost when quantity is changed
>     function UpdateCost(number, unitcost) {
>        costname = "cost" + number;
>        qtyname = "qty" + number;
>        var q = document.order[qtyname].value;
>        document.order[costname].value = q * unitcost;
>        Total();
>     }
>     </SCRIPT>
>     </HEAD>
>     <BODY>
>     <H1>Order Form</H1>
>     <FORM NAME="order">
>     <B>Name:</B> <INPUT TYPE="text" NAME="name1" SIZE=20>
>     <B>Phone: </B><INPUT TYPE="text" NAME="phone" SIZE=15>
>     <B>E-mail address:</B><INPUT TYPE="text" NAME="email" SIZE=20><BR>
>     <B>Billing and Shipping Addresses:</B><BR>
>     <TEXTAREA NAME="billto" COLS=40 ROWS=4>
>     Enter your billing address here.
>     </TEXTAREA>
>     <TEXTAREA NAME="shipto" COLS=40 ROWS=4>
>     Enter your shipping address here.
>     </TEXTAREA>
>     <B>Products to Order:</B><BR>
>     Qty: <INPUT TYPE="TEXT" NAME="qty1" VALUE="0" SIZE=4
>     onChange = "UpdateCost(1, 40.00);">
>     Cost: <INPUT TYPE="TEXT" NAME="cost1" SIZE=6>
>     ($40.00 ea) Fictional Spreadsheet 7.0 <BR>
>     Qty: <INPUT TYPE="TEXT" NAME="qty2" VALUE="0" SIZE=4
>     onChange = "UpdateCost(2, 69.95);">
>     Cost: <INPUT TYPE="TEXT" NAME="cost2" SIZE=6>
>     ($69.95 ea) Fictional Word Processor 6.0<BR>
>     Qty: <INPUT TYPE="TEXT" NAME="qty3" VALUE="0" SIZE=4
>     onChange = "UpdateCost(3, 99.95);">
>     Cost: <INPUT TYPE="TEXT" NAME="cost3" SIZE=6>
>     ($99.95 ea) Fictional Database 7.0 <BR>
>     Qty: <INPUT TYPE="TEXT" NAME="qty4" VALUE="0" SIZE=4
>     onChange = "UpdateCost(4, 4.95);">
>     Cost: <INPUT TYPE="TEXT" NAME="cost4" SIZE=6>
>     ($4.95 ea) Instruction Booklet for the above <HR>
>     <B>Total Cost:</B>
>     <INPUT TYPE="TEXT" NAME="totalcost" SIZE=8><HR>
>     <B>Method of Payment</B>:
>     <SELECT NAME="payby">
>     <OPTION VALUE="check" SELECTED>Check or Money Order
>     <OPTION VALUE="cash">Cash or Cashier's Check
>     <OPTION VALUE="credit">Credit Card (specify number)
>     </SELECT><BR>
>     <B>Credit Card or Check Number:</B>:
>     <INPUT TYPE="TEXT" NAME="creditno" SIZE="20"><BR>
>     <INPUT TYPE="SUBMIT" NAME="submit" VALUE="Send Your Order">
>     <INPUT TYPE="RESET" VALUE="Start Over">
>     </FORM>
>     </BODY>
>     </HTML>

## Automating the Shipping Address

Because the order form includes spaces for separate billing and shipping addresses, it's a good idea to give the user an option to use the same address for both. Using JavaScript, you can add such an option easily-and it makes for a neat bit of automation.

To accomplish this, you'll add a checkbox above the addresses and label it:

>     <INPUT TYPE="chECKBOX" NAME="same" onClick="CopyAddress();">
>     Ship to Billing Address

You'll use the `onClick` event handler for the checkbox to handle the copying. Here is the `CopyAddress` function for copying the address:

>     // function to copy billing address to shipping address
>     function CopyAddress() {
>        if (document.order.same.checked) {
>           document.order.shipto.value = document.order.billto.value;
>        }
>     }

This function checks the `checked` property of the checkbox, and if it's currently checked, it copies the billing address to the shipping address.

This works when the checkbox is checked, but what about when the user changes the billing address after checking the box? You will use the `onChange` event handler to do the copy again whenever the billing address changes:

>     <TEXTAREA NAME="billto" COLS=40 ROWS=4 onChange="CopyAddress();">
>     Enter your billing address here.
>     </TEXTAREA>

There's one possibility left: after checking the box, the user might mistakenly change the shipping address. Because you want the addresses to be the same, you use the same event handler on the shipping address. Therefore, when the user changes
the shipping address with the box checked, it will immediately be changed back to the billing address.

Listing 6.3 is the latest version of the HTML form, including the automatic address-copying function you just added. Figure 6.5 shows how the new form looks in Netscape.

Figure 6.5 : The order form with address-copying feature.

> Listing 6.3. The revised HTML order form with the address-copying features.

>     <HTML>
>     <HEAD><TITLE>Order Form</TITLE>
>     <SCRIPT>
>     // function to calculate the total cost field
>     function Total() {
>        var tot = 0;
>        tot += (40.00 * document.order.qty1.value);
>        tot += (69.95 * document.order.qty2.value);
>        tot += (99.95 * document.order.qty3.value);
>        tot += (4.95 * document.order.qty4.value);
>        document.order.totalcost.value = tot;
>     }

>     // function to update cost when quantity is changed
>     function UpdateCost(number, unitcost) {
>        costname = "cost" + number;
>        qtyname = "qty" + number;
>        var q = document.order[qtyname].value;
>        document.order[costname].value = q * unitcost;
>        Total();
>     }

>     // function to copy billing address to shipping address
>     function CopyAddress() {
>        if (document.order.same.checked) {
>           document.order.shipto.value = document.order.billto.value;
>        }
>     }

>     </SCRIPT>
>     </HEAD>
>     <BODY>
>     <H1>Order Form</H1>
>     <FORM NAME="order">
>     <B>Name:</B> <INPUT TYPE="text" NAME="name1" SIZE=20>
>     <B>Phone: </B><INPUT TYPE="text" NAME="phone" SIZE=15>
>     <B>E-mail address:</B><INPUT TYPE="text" NAME="email" SIZE=20><BR>
>     <B>Billing and Shipping Addresses:</B>
>     <INPUT TYPE="chECKBOX" NAME="same" onClick="CopyAddress();">
>     Ship to Billing Address
>     <BR>
>     <TEXTAREA NAME="billto" COLS=40 ROWS=4 onChange="CopyAddress();">
>     Enter your billing address here.
>     </TEXTAREA>
>     <TEXTAREA NAME="shipto" COLS=40 ROWS=4 onChange="CopyAddress();">
>     Enter your shipping address here.
>     </TEXTAREA>
>     <B>Products to Order:</B><BR>
>     Qty: <INPUT TYPE="TEXT" NAME="qty1" VALUE="0" SIZE=4
>     onChange = "UpdateCost(1, 40.00);">
>     Cost: <INPUT TYPE="TEXT" NAME="cost1" SIZE=6>
>     ($40.00 ea) Fictional Spreadsheet 7.0 <BR>
>     Qty: <INPUT TYPE="TEXT" NAME="qty2" VALUE="0" SIZE=4
>     onChange = "UpdateCost(2, 69.95);">
>     Cost: <INPUT TYPE="TEXT" NAME="cost2" SIZE=6>
>     ($69.95 ea) Fictional Word Processor 6.0<BR>
>     Qty: <INPUT TYPE="TEXT" NAME="qty3" VALUE="0" SIZE=4
>     onChange = "UpdateCost(3, 99.95);">
>     Cost: <INPUT TYPE="TEXT" NAME="cost3" SIZE=6>
>     ($99.95 ea) Fictional Database 7.0 <BR>
>     Qty: <INPUT TYPE="TEXT" NAME="qty4" VALUE="0" SIZE=4
>     onChange = "UpdateCost(4, 4.95);">
>     Cost: <INPUT TYPE="TEXT" NAME="cost4" SIZE=6>
>     ($4.95 ea) Instruction Booklet for the above <HR>
>     <B>Total Cost:</B>
>     <INPUT TYPE="TEXT" NAME="totalcost" SIZE=8><HR>
>     <B>Method of Payment</B>:
>     <SELECT NAME="payby">
>     <OPTION VALUE="check" SELECTED>Check or Money Order
>     <OPTION VALUE="cash">Cash or Cashier's Check
>     <OPTION VALUE="credit">Credit Card (specify number)
>     </SELECT><BR>
>     <B>Credit Card or Check Number:</B>:
>     <INPUT TYPE="TEXT" NAME="creditno" SIZE="20"><BR>
>     <INPUT TYPE="SUBMIT" NAME="submit" VALUE="Send Your Order">
>     <INPUT TYPE="RESET" VALUE="Start Over">
>     </FORM>
>     </BODY>
>     </HTML>

## Validating the Form Data with Event Handlers

The final feature you can add to a form with JavaScript is perhaps the most important: validation. This means checking each field to ensure that it contains a proper value and advising the user if it is incorrect.

Obviously, validating can only do so much. For example, you can't tell whether a phone number is valid or whether a name is an alias. You can tell whether it exists, though, and whether it's in the right format.

Validation saves you some trouble when you receive a response. More importantly, it saves you the trouble of performing the validation in the CGI script. This enables you to use a generic CGI script, and enables the user to receive immediate feedback without waiting on the server.

### Where to Validate?

You could use the `onChange` event handler on each of the fields to validate it. For example, as soon as users enter their names and move to the next field, you could alert them if the names are invalid.

This method is worth considering in some cases, but for most forms it's best to validate all the fields at once, using the form's `onSubmit` event handler. This enables users to correct any fields necessary, then press submit when they're really ready.

For the FSC order form, you will use a single `onSubmit` event handler to perform the validation for all the fields.

Tip
If you choose to validate fields as they change, you might find it useful to use the `this` keyword. Within an event handler, `this` represents the object that triggered the event. This technique enables you to use a single validation routine for several fields.

### Which Fields to Validate?

When choosing how to handle validation for a form, the first step is to decide which fields you need to validate and what to check for. For some items, such as a name, the most you can do is see whether anything is entered.

For other items you can be more specific; for example, if your form asked for the user's age, you can check for numbers over 100 or so. (I would suggest a lower limit, but the Internet audience is getting younger every day.)

For the FSC order form, let's use the following validation criteria:

- The name must be at least 6 characters, and the billing address and shipping address must be at least 30 characters. The phone number must be at least 10 characters. (You want them to include the area code.)
- The e-mail address must be at least 5 characters and include the `@` symbol.
- Because the cost fields are calculated automatically, you won't bother validating them. However, you'll check the total cost; if it's `0` or blank, they haven't ordered anything.
- If the payment method is anything but cash, the credit card number/check number field must be at least 2 characters.

Obviously, you could make some of these more specific, but they'll do to illustrate the concept. You'll need to choose the appropriate values for each form with which you work.

## Creating Functions for Validation

Based on the decisions made previously, you now need to create a function to handle each of the fields. In some cases, you can use the same function for multiple fields. Let's start with the simplest function: checking for the proper length. This function will work with the name, billing address, and phone number fields.

>     function ValidLength(item, len) {
>        return (item.length >= len);

`}`

This function expects the name of an item and the required length. It simply checks whether the item is greater than or equal to that length, and it returns true or false appropriately.

Next, let's create a function for the e-mail address. This will simply call the `ValidLength` function to check the length, then use the `indexOf` string method to check for the `@` sign:

>     //function to validate an email address
>     function ValidEmail(item) {
>        if (!ValidLength(item, 5)) return false;
>        if (item.indexOf ('@', 0) == -1) return false;
>        return true;
>     }

Finally, let's create a main validation routine. This routine validates all the fields one at a time, then returns true or false:

>     function Validate() {
>        errfound = false;
>        if (!ValidLength(document.order.name1.value,6))
>           error(document.order.name1,"Invalid Name");
>        if (!ValidLength(document.order.phone.value,10))
>           error(document.order.phone,"Invalid Phone");
>        if (!ValidLength(document.order.billto.value,30))
>           error(document.order.billto,"Invalid Billing Address");
>        if (!ValidLength(document.order.shipto.value,30))
>           error(document.order.shipto,"Invalid Shipping Address");
>        if (!ValidEmail(document.order.email.value))
>           error(document.order.email, "Invalid Email Address");
>        if (document.order.totalcost.value == "")
>           error(document.order.qty1, "Please Order at least one item.");
>        if (document.order.payby.selectedIndex != 1) {
>           if (!ValidLength(document.order.creditno.value,2))
>              error(document.order.creditno,"Invalid Credit/Check number");
>        }
>        return !errfound; /* true if there are no errors */
>     }

As you can see, this function includes tests for the length-related functions and the e-mail address; in addition, I have added checks for the credit card number and the total cost. If any of these checks fails, an error routine is called:

>     function error(elem, text) {
>     // abort if we already found an error
>        if (errfound) return;
>        window.alert(text);
>        elem.select();
>        elem.focus();
>        errfound = true;
>     }

This function displays a dialog explaining the error, then sets the focus to the element with the error; this positions the cursor in that field so the user can easily change it. In addition, the `select` method is used to select the item's text.

Note
Because the user doesn't normally enter data in the total cost field, the validate routine points the cursor to the first quantity field, so the user can add an item to the order.

One more thing: the `error` function sets a variable, `errfound`, to indicate that an error has happened. It returns immediately if an error was already found; this prevents multiple dialogs from showing if more than one field is invalid.

## Adding an Event Handler for Validation

Finally, you can link the validation routine to the form itself. You will add an `onSubmit` event handler to the `FORM` declaration:

>     <FORM NAME="order" onSubmit="return Validate();">

This calls the `Validate` function and uses its return value as the return value of the event. This means that if `Validate` returns false-in other words, if something is invalid-the data will not be submitted.

This basically completes the order form. Listing 6.4 is the complete HTML listing, including all the validation scripting. The complete form is shown in Figure 6.6, including a dialog indicating that the e-mail address is invalid.

Figure 6.6 : The complete HTML order form, including validation for all fields.

> Listing 6.4. The revised HTML order form with validation.

>     <HTML>
>     <HEAD><TITLE>Order Form</TITLE>
>     <SCRIPT>
>     // function to calculate the total cost field
>     function Total() {
>        var tot = 0;
>        tot += (40.00 * document.order.qty1.value);
>        tot += (69.95 * document.order.qty2.value);
>        tot += (99.95 * document.order.qty3.value);
>        tot += (4.95 * document.order.qty4.value);
>        document.order.totalcost.value = tot;
>     }
>     // function to update cost when quantity is changed
>     function UpdateCost(number, unitcost) {
>        costname = "cost" + number;
>        qtyname = "qty" + number;
>        var q = document.order[qtyname].value;
>        document.order[costname].value = q * unitcost;
>        Total();
>     }
>     // function to copy billing address to shipping address
>     function CopyAddress() {
>        if (document.order.same.checked) {
>           document.order.shipto.value = document.order.billto.value;
>        }
>     }
>     //global variable for error flag
>     var errfound = false;
>     //function to validate by length
>     function ValidLength(item, len) {
>        return (item.length >= len);
>     }
>     //function to validate an email address
>     function ValidEmail(item) {
>        if (!ValidLength(item, 5)) return false;
>        if (item.indexOf ('@', 0) == -1) return false;
>        return true;
>     }
>     // display an error alert
>     function error(elem, text) {
>     // abort if we already found an error
>        if (errfound) return;
>        window.alert(text);
>        elem.select();
>        elem.focus();
>        errfound = true;
>     }
>     // main validation function
>     function Validate() {
>        errfound = false;
>        if (!ValidLength(document.order.name1.value,6))
>           error(document.order.name1,"Invalid Name");
>        if (!ValidLength(document.order.phone.value,10))
>           error(document.order.phone,"Invalid Phone");
>        if (!ValidLength(document.order.billto.value,30))
>           error(document.order.billto,"Invalid Billing Address");
>        if (!ValidLength(document.order.shipto.value,30))
>           error(document.order.shipto,"Invalid Shipping Address");
>        if (!ValidEmail(document.order.email.value))
>           error(document.order.email, "Invalid Email Address");
>        if (document.order.totalcost.value == "")
>           error(document.order.qty1, "Please Order at least one item.");
>        if (document.order.payby.selectedIndex != 1) {
>           if (!ValidLength(document.order.creditno.value,2))
>              error(document.order.creditno,"Invalid Credit/Check number");
>        }
>        return !errfound; /* true if there are no errors */
>     }
>     </SCRIPT>
>     </HEAD>
>     <BODY>
>     <H1>Order Form</H1>
>     <FORM NAME="order" onSubmit="return Validate();">
>     <B>Name:</B> <INPUT TYPE="text" NAME="name1" SIZE=20>
>     <B>Phone: </B><INPUT TYPE="text" NAME="phone" SIZE=15>
>     <B>E-mail address:</B><INPUT TYPE="text" NAME="email" SIZE=20><BR>
>     <B>Billing and Shipping Addresses:</B>
>     <INPUT TYPE="chECKBOX" NAME="same" onClick="CopyAddress();">
>     Ship to Billing Address
>     <BR>
>     <TEXTAREA NAME="billto" COLS=40 ROWS=4 onChange="CopyAddress();">
>     Enter your billing address here.
>     </TEXTAREA>
>     <TEXTAREA NAME="shipto" COLS=40 ROWS=4 onChange="CopyAddress();">
>     Enter your shipping address here.
>     </TEXTAREA>
>     <B>Products to Order:</B><BR>
>     Qty: <INPUT TYPE="TEXT" NAME="qty1" VALUE="0" SIZE=4
>     onChange = "UpdateCost(1, 40.00);">
>     Cost: <INPUT TYPE="TEXT" NAME="cost1" SIZE=6>
>     ($40.00 ea) Fictional Spreadsheet 7.0 <BR>
>     Qty: <INPUT TYPE="TEXT" NAME="qty2" VALUE="0" SIZE=4
>     onChange = "UpdateCost(2, 69.95);">
>     Cost: <INPUT TYPE="TEXT" NAME="cost2" SIZE=6>
>     ($69.95 ea) Fictional Word Processor 6.0<BR>
>     Qty: <INPUT TYPE="TEXT" NAME="qty3" VALUE="0" SIZE=4
>     onChange = "UpdateCost(3, 99.95);">
>     Cost: <INPUT TYPE="TEXT" NAME="cost3" SIZE=6>
>     ($99.95 ea) Fictional Database 7.0 <BR>
>     Qty: <INPUT TYPE="TEXT" NAME="qty4" VALUE="0" SIZE=4
>     onChange = "UpdateCost(4, 4.95);">
>     Cost: <INPUT TYPE="TEXT" NAME="cost4" SIZE=6>
>     ($4.95 ea) Instruction Booklet for the above <HR>
>     <B>Total Cost:</B>
>     <INPUT TYPE="TEXT" NAME="totalcost" SIZE=8><HR>
>     <B>Method of Payment</B>:
>     <SELECT NAME="payby">
>     <OPTION VALUE="check" SELECTED>Check or Money Order
>     <OPTION VALUE="cash">Cash or Cashier's Check
>     <OPTION VALUE="credit">Credit Card (specify number)
>     </SELECT><BR>
>     <B>Credit Card or Check Number:</B>:
>     <INPUT TYPE="TEXT" NAME="creditno" SIZE="20"><BR>
>     <INPUT TYPE="SUBMIT" NAME="submit" VALUE="Send Your Order">
>     <INPUT TYPE="RESET" VALUE="Start Over">
>     </FORM>
>     </BODY>
>     </HTML>

Tip
At this point, submitting the form won't do anything; however, you can still test the submission. Submitting will reload the current page and add the various data to the URL.

## Workshop Wrap-Up

In this chapter, you built a fully functional ordering system for an imaginary company, which could easily be modified for use by a real company. In the process, you learned the following:

- How to use HTML forms and their many elements in a Web page
- How to use JavaScript to add validation to the form
- How to use JavaScript to add automation to a form
- About the `<FORM>` object and form elements, and how to manipulate and read each of their values in JavaScript

### Next Steps

You should now know how to use JavaScript with forms. To move on, turn to one of the following chapters:

- To learn about the object hierarchy that underlies forms, see Chapter 5 "Accessing Window Elements as Objects."
- To see another example of form validation, turn to Chapter 7, "Real-Life Examples I."
- To learn to add functionality to a Web page, such as navigation bars and the status line, see Chapter 8 "Improving a Web Page with JavaScript."
- To learn about advanced browser features such as frames, see Chapter 9 "Using Frames, Cookies, and Other Advanced Features."
- To learn more about CGI and interactive forms, see Chapter 17, "Combining JavaScript, CGI and SSI."

### Q&A

Q: | Is there any way to force a form to be submitted automatically, without the user pressing a button?
A: | Yes. You can do this with the `form.submit()` method. However, this is bad manners; it's usually best to let the user know what's going on. Also note that due to security concerns, you can't do this with a form that uses the `mailto` action.
Q: | I am having problems trying to force a checkbox to be selected using the `click` method. Is there a way to solve this?
A: | Unfortunately, at least for many versions of Netscape, the only solution is not to use the `click` method. Fortunately, it's easy to do most things without it. For a checkbox, you can manipulate the `checked` property; for a button, you can call the same function as its `onClick` event handler.
Q: | If I use JavaScript to add validation and other features to my form, can users with non-JavaScript browsers still use the form?
A: | Yes, if you're careful. Be sure to use a SUBMIT button rather than the `submit` action. Also, because the CGI script may receive nonvalidated data, be sure to include validation in the CGI script. Non-JavaScript users will be able to use the form but won't receive instant feedback about their errors.
Q: | Can I add new form elements "on the fly," or change them-for example, change a text box into a password field?
A: | No. The form elements are set by the HTML code. There are ways to work around this, such as updating the form in a separate frame.
Q: | Is there any way to create a large number of text fields without dealing with different names for all of them?
A: | Yes. If you use the same name for several elements in the form, their objects will form an array. For example, if you defined 20 text fields with the name `member`, you could refer to them as `member[0]` through `member[19]`. Chapter 15, "Real-Life Examples III," uses this technique for score values in a game.
Q: | When validating an e-mail address, is there any way to be sure the address is valid, or that it is the user's address?
A: | No. This is a classic question about CGI; neither JavaScript nor CGI has a good solution. The only way to be sure an e-mail address is valid is to send information, such as a password, to the address; even then, you can't be sure users are entering their own addresses.
Q: | Why doesn't JavaScript recognize my form elements when I use a table to lay them out?
A: | JavaScript does not deal well with forms within tables when `<TABLE>` tags are nested. For now, the only solution is to avoid using nested tables.
Q: | Is there a way to place the cursor on a particular field when the form is loaded?
A: | Yes. You can use the field's `focus()` method to send the cursor there. The best way to do this is to use an `onLoad` event handler and add a slight delay with the `setTimeout()` method to allow the page to finish loading.